package com.cafuc.thread;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadOperation {
    private static int a = 0;
    private static int b = 0;
    public final static Object lockA = new Object();
    public final static Object lockB = new Object();
    public void lock1(){
        synchronized (lockA){
            a ++;
            synchronized (lockB){
                b ++;
            }
        }
    }

    public void lock2(){
        synchronized (lockA){
            a --;
            synchronized (lockB){
                b --;
            }
        }
    }

    public final Lock lock = new ReentrantLock();
    public void locMethod() throws InterruptedException {
        if(lock.tryLock(3, TimeUnit.SECONDS)){
            //能够获取锁
            lock.lock();
            try {
                a ++;
            }finally {
                lock.unlock();
            }
        }
        else{
            //不能获取锁

        }
    }

    public synchronized void add(){
        if(a > 10000){
            dec();
        }
        else{
            a ++;
        }
    }

    public synchronized void dec(){
        if(a < 0){
            add();
        }
        else{
            a --;
        }
    }

    public void threadTest(){
        System.out.println("==== 开启主线程 ====");


        //方式一：继承Thrad
        MyThread myThread = new MyThread();
        myThread.start();

        //方式二：实现 Runnable
        MyRunnable myRunnable = new MyRunnable();
        new Thread(myRunnable).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("==== 匿名内部类开启 Runnable 线程 ====");
            }
        }).start();

        new Thread(() -> System.out.println("==== Lambda 开启 Runnable 线程 ====")).start();

        //方式三：实现 Callable 接口
        MyCallable myCallable = new MyCallable();
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future<String> future =  executorService.submit(myCallable);
        try {
            System.out.println(future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        executorService.shutdown();

    }

    public void synchThreadTest() throws Exception {
        Thread thread1 = new Thread(() -> {
            for(int i = 0 ; i < 10000; i ++){
                synchronized (this){
                    a ++;
                }
            }
        });
        Thread thread2 = new Thread(() -> {
            for(int i = 0 ; i < 10000; i ++){
                synchronized (this){
                    a --;
                }
            }
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();

        System.out.println(a);
    }

    public void fixedThreadPool(){
        ExecutorService es = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 4; i++){
            es.submit(new MyRunnable(i + ""));
        }
        es.shutdown();
    }

    public static void main(String[] args) throws Exception {

        ThreadOperation to = new ThreadOperation();
        // to.threadTest();
       // for(int i =0; i < 100; i ++){
       //     to.synchThreadTest();
       // }
       //
       //
       // for(int i = 0; i < 100; i ++){
       //     System.out.println(new AtomicLong(0).incrementAndGet());
       // }
        to.fixedThreadPool();
    }
}
